package downloader

import (
	"crypto/tls"
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"syscall"

	"go.uber.org/zap"
)

// Downloader 下载器结构体
// 示例值: downloadDir="/tmp/ssh-upgrade"
type Downloader struct {
	downloadDir    string
	skipTLSVerify bool
}

// NewDownloader 创建下载器
// 示例值: downloadDir="/tmp/ssh-upgrade"
func NewDownloader(downloadDir string, skipTLSVerify bool) *Downloader {
	return &Downloader{
		downloadDir:    downloadDir,
		skipTLSVerify: skipTLSVerify,
	}
}

// DownloadFile 下载文件
// 示例值: url="https://example.com/file.tar.gz", filename="file.tar.gz"
func (d *Downloader) DownloadFile(url, filename string) error {
	zap.L().Info("开始下载文件", zap.String("url", url), zap.String("filename", filename))

	// 创建下载目录
	if err := os.MkdirAll(d.downloadDir, 0755); err != nil {
		return fmt.Errorf("创建下载目录失败: %v", err)
	}

	// 下载文件
	filePath := filepath.Join(d.downloadDir, filename)
	if err := d.downloadWithProgress(url, filePath); err != nil {
		return fmt.Errorf("下载失败: %v", err)
	}

	zap.L().Info("文件下载完成", zap.String("filePath", filePath))
	return nil
}

// downloadWithProgress 带进度显示的下载
// 示例值: url="https://example.com/file.tar.gz", filePath="/tmp/ssh-upgrade/file.tar.gz"
func (d *Downloader) downloadWithProgress(url, filePath string) error {
	// 创建HTTP客户端
	client := d.createHTTPClient()

	// 发送请求
	resp, err := client.Get(url)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	// 检查响应状态
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("HTTP错误: %s", resp.Status)
	}

	// 创建文件
	file, err := os.Create(filePath)
	if err != nil {
		return err
	}
	defer file.Close()

	// 复制数据并显示进度
	_, err = io.Copy(file, resp.Body)
	return err
}

// createHTTPClient 创建HTTP客户端
// 示例值: 无参数
func (d *Downloader) createHTTPClient() *http.Client {
	client := &http.Client{}
	
	// 如果启用跳过TLS证书验证
	if d.skipTLSVerify {
		transport := &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		}
		client.Transport = transport
		zap.L().Info("已启用跳过HTTPS证书检测模式")
	}
	
	return client
}

// CheckDiskSpace 检查磁盘空间
// 示例值: requiredSpace=int64(100*1024*1024)
func (d *Downloader) CheckDiskSpace(requiredSpace int64) error {
	var stat syscall.Statfs_t
	if err := syscall.Statfs(d.downloadDir, &stat); err != nil {
		return fmt.Errorf("获取磁盘信息失败: %v", err)
	}

	// 计算可用空间
	availableSpace := int64(stat.Bavail) * int64(stat.Bsize)
	if availableSpace < requiredSpace {
		return fmt.Errorf("磁盘空间不足，需要: %dMB，可用: %dMB",
			requiredSpace/(1024*1024), availableSpace/(1024*1024))
	}

	zap.L().Info("磁盘空间检查通过", zap.Int64("availableMB", availableSpace/(1024*1024)))
	return nil
}

// CleanupDownloadDir 清理下载目录
// 示例值: 无参数
func (d *Downloader) CleanupDownloadDir() error {
	zap.L().Info("清理下载目录")

	// 检查目录是否存在
	if info, err := os.Stat(d.downloadDir); err != nil || !info.IsDir() {
		zap.L().Info("下载目录不存在，跳过清理")
		return nil
	}

	// 删除目录
	if err := os.RemoveAll(d.downloadDir); err != nil {
		zap.L().Warn("清理下载目录失败", zap.Error(err))
		return err
	}

	zap.L().Info("下载目录清理完成", zap.String("downloadDir", d.downloadDir))
	return nil
}

// MirrorChecker 镜像检查器
// 示例值: 无参数
type MirrorChecker struct {
	skipTLSVerify bool
}

// NewMirrorChecker 创建镜像检查器
// 示例值: 无参数
func NewMirrorChecker(skipTLSVerify bool) *MirrorChecker {
	return &MirrorChecker{
		skipTLSVerify: skipTLSVerify,
	}
}

// CheckMirrorAvailability 检查镜像地址可用性
// 示例值: mirror="https://mirrors.aliyun.com/openssh/portable/"
func (m *MirrorChecker) CheckMirrorAvailability(mirror string) bool {
	zap.L().Info("检查镜像地址可用性", zap.String("mirror", mirror))

	// 创建HTTP客户端
	client := m.createHTTPClient()

	// 简单的HTTP HEAD请求检查
	resp, err := client.Head(mirror)
	if err != nil {
		zap.L().Warn("镜像地址检查失败", zap.Error(err))
		return false
	}
	defer resp.Body.Close()

	// 检查HTTP状态码
	if resp.StatusCode >= 200 && resp.StatusCode < 400 {
		zap.L().Info("镜像地址可用", zap.String("mirror", mirror), zap.Int("statusCode", resp.StatusCode))
		return true
	}

	zap.L().Warn("镜像地址不可用", zap.String("mirror", mirror), zap.Int("statusCode", resp.StatusCode))
	return false
}

// createHTTPClient 创建HTTP客户端
// 示例值: 无参数
func (m *MirrorChecker) createHTTPClient() *http.Client {
	client := &http.Client{}
	
	// 如果启用跳过TLS证书验证
	if m.skipTLSVerify {
		transport := &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		}
		client.Transport = transport
		zap.L().Info("镜像检查器已启用跳过HTTPS证书检测模式")
	}
	
	return client
}
